#include "../../../Include/DataType/Color/WizDataTypeColor.hpp"


namespace Wiz
{
    //////////////////////////////////////////////////////////////////////////
    namespace Color
    {
        template<class T>
        WIZ_INLINE T Clamp(const T& v, const T& Min_v, const T& Max_v)
        {
            return v < Min_v ? Min_v : v > Max_v ? Max_v : v;
        }

        template<class T>
        WIZ_INLINE T Saturate(const T& v)
        {
            return ::Wiz::Color::Clamp<T>(v, 0, 1);
        }

        Type::Type()
        {}
        Type::Type
            (
            ::Wiz::Real::In red,
            ::Wiz::Real::In green,
            ::Wiz::Real::In blue,
            ::Wiz::Real::In alpha
            )
        {
            r = ::Wiz::Color::Saturate(red);
            g = ::Wiz::Color::Saturate(green);
            b = ::Wiz::Color::Saturate(blue);
            a = ::Wiz::Color::Saturate(alpha);
        }

        ::Wiz::Void::Type Type::Saturate()
        {
            r = ::Wiz::Color::Saturate(r);
            g = ::Wiz::Color::Saturate(g);
            b = ::Wiz::Color::Saturate(b);
            a = ::Wiz::Color::Saturate(a);
        }
        ::Wiz::Void::Type Type::From(
            ::Wiz::UInt8::In    red,
            ::Wiz::UInt8::In    green,
            ::Wiz::UInt8::In    blue,
            ::Wiz::UInt8::In    alpha
            )
        {
            const ::Wiz::Real::Type omax = 1 / ::Wiz::Cast::Static<::Wiz::Real::Type>(::Wiz::UInt8::Max);
            r = ::Wiz::Cast::Static<::Wiz::Real::Type>(red)    * omax;
            g = ::Wiz::Cast::Static<::Wiz::Real::Type>(green)  * omax;
            b = ::Wiz::Cast::Static<::Wiz::Real::Type>(blue)   * omax;
            a = ::Wiz::Cast::Static<::Wiz::Real::Type>(alpha)  * omax;
        }

        ::Wiz::Void::Type Type::FromRGBA(::Wiz::UInt32::In color)
        {
            ::Wiz::RGBA::Type* pColor = (::Wiz::RGBA::Type*)(&color);

            this->From(pColor->r, pColor->g, pColor->b, pColor->a);
        }

        ::Wiz::Void::Type Type::FromARGB(::Wiz::UInt32::In color)
        {
            ::Wiz::ARGB::Type* pColor = (::Wiz::ARGB::Type*)(&color);

            this->From(pColor->r, pColor->g, pColor->b, pColor->a);
        }

        ::Wiz::Void::Type Type::FromABGR(::Wiz::UInt32::In color)
        {
            ::Wiz::ABGR::Type* pColor = (::Wiz::ABGR::Type*)(&color);

            this->From(pColor->r, pColor->g, pColor->b, pColor->a);
        }

        ::Wiz::Void::Type Type::FromBGRA(::Wiz::UInt32::In color)
        {
            ::Wiz::BGRA::Type* pColor = (::Wiz::BGRA::Type*)(&color);

            this->From(pColor->r, pColor->g, pColor->b, pColor->a);
        }
        ::Wiz::Void::Type Type::To
            (
            ::Wiz::UInt8::Out    red,
            ::Wiz::UInt8::Out    green,
            ::Wiz::UInt8::Out    blue,
            ::Wiz::UInt8::Out    alpha
            ) const 
        {
            red     = (::Wiz::UInt8::Type)(this->r * 255);
            green   = (::Wiz::UInt8::Type)(this->g * 255);
            blue    = (::Wiz::UInt8::Type)(this->b * 255);
            alpha   = (::Wiz::UInt8::Type)(this->a * 255);
        }

        ::Wiz::UInt32::Type Type::ToRGBA() const
        {
            ::Wiz::UInt32::Type color;
            ::Wiz::RGBA::Type* pColor = (::Wiz::RGBA::Type*)(&color);
            this->To(pColor->r, pColor->g, pColor->b, pColor->a);
            return color;
        }

        ::Wiz::UInt32::Type Type::ToARGB() const
        {
            ::Wiz::UInt32::Type color;
            ::Wiz::ARGB::Type* pColor = (::Wiz::ARGB::Type*)(&color);
            this->To(pColor->r, pColor->g, pColor->b, pColor->a);
            return color;
        }

        ::Wiz::UInt32::Type Type::ToABGR() const
        {
            ::Wiz::UInt32::Type color;
            ::Wiz::ABGR::Type* pColor = (::Wiz::ABGR::Type*)(&color);
            this->To(pColor->r, pColor->g, pColor->b, pColor->a);
            return color;
        }

        ::Wiz::UInt32::Type Type::ToBGRA() const
        {
            ::Wiz::UInt32::Type color;
            ::Wiz::BGRA::Type* pColor = (::Wiz::BGRA::Type*)(&color);
            this->To(pColor->r, pColor->g, pColor->b, pColor->a);
            return color;
        }
    } /// end of namespace color
    //////////////////////////////////////////////////////////////////////////
} /// end of namespace Wiz

